
#pragma once
#include "uimgr.h"
#include "resmgr.h"

//已删除部分注释

//Clickable
//////////////////////////////////////////////////////////////////////////
class CButton : public UIControl
{
public:
	WCHAR* Text;
	BOOL FlatStyle;
    int ColorIndex;
	ImageR_t* ImgNormal;
	ImageR_t* ImgHover;
	ImageR_t* ImgPush;
	ImageR_t* ImgDisable;
	FontR_t* FontText;

	//按钮自带图像，可直接使用
	//对于图像式按钮，受资源限制，最小不能低于23*23，否则贴图出现错误
	//对于平坦式按钮，受字体限制，高度不能低于18（字体14，描边2，边框2）
	CButton(WCHAR* Name,int X,int Y,int Width,int Height,WCHAR* Text,BOOL FlatStyle);
	virtual ~CButton();
	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);

	void SetText(WCHAR* Text);
	WCHAR* GetText();
    //0-橙 1-红 2-青 3-绿 4-紫
	void SetFlatColor(int Index);
};

class CImage : public UIControl
{
public:
	ImageR_t* ImgMain;
	ImageR_t* ImgHover;
	ImageR_t* ImgPush;
	ImageR_t* ImgDisable;
	BOOL ImageScale;

	CImage(WCHAR* Name,int X,int Y,int Width,int Height);
	virtual ~CImage();
	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);

	//ImgHover，ImgPush和ImgDisable为NULL时，均使用ImgMain绘制
	//允许ImgMain为NULL，等价于一个接受输入的透明控件
	void SetImage(ImageR_t* ImgMain);
	void SetHoverImage(ImageR_t* ImgHover);
	void SetPushImage(ImageR_t* ImgHover);
	void SetDisableImage(ImageR_t* ImgDisable);
	void EnableImageScale(BOOL Enable);
};

class CLabel : public UIControl
{
public:
	WCHAR* Text;
	DWORD Color;
	DWORD BackColor;
	DWORD BorderColor;
	FontR_t* FontText;
	int Padding;
	int LineSpace;

	//字体高度14，内边距自定
	CLabel(WCHAR* Name,int X,int Y,int Width,int Height,WCHAR* Text);
	virtual ~CLabel();
	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);

	//遇到\n时，或字符宽度满一行时，自动换行（仅支持左对齐）
	void SetText(WCHAR* Text);
	WCHAR* GetText();
	void SetTextColor(DWORD ColorArgb);
	void SetBackColor(DWORD ColorArgb);
	//设为0x00000000时视为隐藏边框
	void SetBorderColor(DWORD ColorArgb);
	void SetPadding(int Padding);
	void SetLineSpace(int LineSpace);
};

class CLineLabel : public UIControl
{
public:
	WCHAR* Text;
	DWORD Color;
	DWORD BackColor;
	DWORD BorderColor;
	DWORD TextBorderColor;
	int AlignSymbol;
	FontR_t* FontText;

	//高度不能小于字体
	static const int MinHeight=14;
	static const int MinHeightWithBorder=16;

	//不设Padding，纵向居中
	CLineLabel(WCHAR* Name,int X,int Y,int Width,int Height,WCHAR* Text);
	virtual ~CLineLabel();
	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);

	//不会折行，\n被忽略
	void SetText(WCHAR* Text);
	WCHAR* GetText();
	void SetTextColor(DWORD ColorArgb);
	void SetBackColor(DWORD ColorArgb);
	//设为0x00000000时视为隐藏边框
	void SetBorderColor(DWORD ColorArgb);
	//设为0x00000000时视为无文字描边
	void SetTextBorderColor(DWORD ColorArgb);
	//左对齐为'<'，右对齐为'>'，居中为'-'
	void SetAlign(int AlignSymbol);
};

class CCheckBox : public UIControl
{
public:
	WCHAR* Text;
	FontR_t* FontText;
	ImageR_t* ImgNormal[2];
	ImageR_t* ImgHover[2];
	ImageR_t* ImgPush[2];
	ImageR_t* ImgDisable[2];
	DWORD TextColor;
	DWORD BackColor;
	BOOL Checked;
	static const int CheckWidth=16;
	static const int CheckHeight=16;
	static const int Padding=2;

	//Checkbox只支持单行文本，高度固定为20（选框16+上下边距各2），根据文本长度自动调节宽度
	//如果要扩大点击区，可以加空格填充
	CCheckBox(WCHAR* Name,int X,int Y,WCHAR* Text);
	virtual ~CCheckBox();
	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);

	//不会折行，\n被忽略
	void SetText(WCHAR* Text);
	WCHAR* GetText();
	void SetCheck(BOOL Checked);
	BOOL IsChecked();
	void SetTextColor(DWORD ColorArgb);
	void SetBackColor(DWORD ColorArgb);
};

//消息框很有用，但是当前暂时没有应用场景，先不实现
class CMsgBox : public UIControl
{
public:
	CMsgBox();
	virtual ~CMsgBox();

	virtual void Draw()=0;
	virtual int Notify(UIEvent_t UIEvent,int Param1,int Param2)=0;
};


//Scrollable
//////////////////////////////////////////////////////////////////////////
class VScrollComponent : public UIComponent
{
public:
	static const int ScrollWidth=16;
	static const int SliderBorderX=1;
	static const int SliderWidth=ScrollWidth-SliderBorderX*2;
	static const int ArrowSize=0;	//箭头宽高均为16，但是不想实现了

	int PageSize;
	int TotalSize;
	int SliderPosY;
	int SliderHeight;
	int BodyPosY;
	int BodyHeight;
	BOOL HoverHit;
	BOOL Dragged;
	int DragPosY;

	VScrollComponent(int Id,UIControl* Owner,int X,int Y);
	virtual ~VScrollComponent();
	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);
	void SetScrollParam(int Height,int PageSize,int TotalSize);
	//UI层面的修改，整数，需要反馈给控件，但反馈数据是小数
	void SetSliderPos(int NewSliderPosY);
	//数据层面的修改，小数，不需要反馈给控件（注意计算前把整数转浮点）
	void SyncScrollData(float ScrollValue);
	int GetBodyHeight();
	int GetSliderPosY();
};

class CVScrollView : public UIControl
{
public:
	ImageR_t* ImgBack;
	int VirtualHeight;
	VScrollComponent* ScrollCpnt;

	CVScrollView(WCHAR* Name,int X,int Y,int Width,int Height);
	virtual ~CVScrollView();
	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);
	virtual int InternalNotify(int Index,UIEvent_t UIEvent,PVOID Param1,PVOID Param2);

	void SetBackImage(ImageR_t* BackImg);
	void SetVirtualHeight(int VirtualHeight);
	void SetHeight(int Height);
	void SetViewPosY(int ViewPosY);
	void SetWidth(int Width);
};

//为简化DropList实现而做出的耦合性组件
class DropListBodyComponent : public UIComponent
{
public:
	DropListBodyComponent(int Id,UIControl* Owner);
	virtual ~DropListBodyComponent();
	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);

	ImageR_t* ImgNormal;
	ImageR_t* ImgHover;
	ImageR_t* ImgPush;
	ImageR_t* ImgDisable;
	BOOL PushedForClick;
};

class DropListListComponent : public UIComponent
{
public:
	DropListListComponent(int Id,UIControl* Owner);
	virtual ~DropListListComponent();
	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);

	BOOL PushedForClick;
	int PushedIndex;
};

class CDropList : public UIControl
{
public:
	//下拉列表有2种模式，一种是纯文本模式，一种是带图标模式
	//纯文本模式高度以字体高度计算，目前固定为16（字体14+上下边距各1）
	//带图标模式支持28*28的图标，高度固定为30（图标28+上下边距各1）
	//受版面限制，下拉列表展开时，最多显示10个，剩余折叠至虚拟视图，通过滚动条翻页
	//28*10+28=308，小于半个窗口高度720/2=360，无论向上展开或向下展开，总有足够空间
	//横向宽度需要自行保证合理，要考虑Padding，图标，文字，下拉按钮/滚动条
	//纵向高度由现有样式计算得到，无需输入
	CDropList(WCHAR* Name,int X,int Y,int Width,BOOL IconStyle);
	virtual ~CDropList();

	static const int IconSize=28;
	static const int TextHeight=14;
	static const int MaxViewItem=10;
	static const int Padding1=1;
	static const int Padding2=2;
	static const int Padding4=4;
	static const int DropBtnSize=16;
	static const int ScrollWidth=16;

	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);
	virtual int InternalNotify(int Index,UIEvent_t UIEvent,PVOID Param1,PVOID Param2);

	int InsertItem(WCHAR* ItemText,int InsertPos);
	int AppendItem(WCHAR* ItemText);
	void DeleteItem(int Index);
	void ClearItem();
	int GetItemNum();
	WCHAR* GetItemText(int Index);
	int FindItem(WCHAR* ItemText,int StartIndex);
	void SetItemData(int Index,PVOID Data);
	PVOID GetItemData(int Index);
    void SetItemText(int Index,WCHAR* ItemText);
	void SetItemIcon(int Index,ImageR_t* Icon);
	void EnableItem(int Index,BOOL Enable);

	void ExpandList();
	void CollapseList();
	void SetSelect(int Index);
	int GetSelect();

	struct ItemData 
	{
		WCHAR* Text;
		BOOL Enable;
		ImageR_t* Icon;
		PVOID UserData;
	};
	//作为选项，DropList内的Item很少变动，选择vector而不是list
	std::vector<ItemData*> ItemArray;
	
	BOOL IconStyle;
	int ItemWidth;
	int ItemHeight;
	int BodyWidth;
	int BodyHeight;
	int ListWidth;
	int ListHeight;

	int SelIndex;
	BOOL ExpandState;
	BOOL DownExpandMode;
	int OldX;
	int OldY;
	int ViewIndex;
	int ViewItemNum;
	int HoverIndex;

	FontR_t* FontText;
	VScrollComponent* ScrollCpnt;
	DropListBodyComponent* BodyCpnt;
	DropListListComponent* ListCpnt;
};

class CSpListBox : public UIControl
{
public:
	CSpListBox(WCHAR* Name,int X,int Y,int Width,int Height);
	virtual ~CSpListBox();

	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);
	virtual int InternalNotify(int Index,UIEvent_t UIEvent,PVOID Param1,PVOID Param2);

	static const int ScrollWidth=16;
	static const int BodyPadding=3;
	static const int ItemPadding=14;
	static const int ParaSpace=8;
	VScrollComponent* ScrollCpnt;
	FontR_t* FontText;
	int SelectLimit;
	int SelectedNum;
	int* SelectIdArray;
	int* SelectIdArray2;
	int SpViewPos;
	int ItemTotalHeight;
	int HoverId;
	BOOL PushedForClick;
	int PushedItemId;
	int ItemAreaWidth;
	int ItemAreaHeight;
	BOOL InvalidPos;
	ImageR_t* ImgBack;
	int BackMode;
	ImageR_t* ImgItemNormal;
	ImageR_t* ImgItemHover;
	ImageR_t* ImgItemSelect;
	ImageR_t* ImgItemSelHover;

	//0-拉伸 1-中心 2-左上角 3-铺满
	void SetBackImage(ImageR_t* ImgBack,int BackMode);

	struct ItemDesc
	{
		int Id;
		int RecordNum;
		WCHAR** Records;
		DWORD* Color;
		int Height;
		BOOL Visible;
		PVOID UserData;
	};

	//单个map只有一种排序方式，目前只支持Id序
	std::map<int,ItemDesc*> ListBoxItems;

	void CreateItem(int Id,int RecordNum);	//需更新高度；关联的Id必须大于等于0，否则会和控件内部实现冲突
	void DeleteItem(int Id);				//需更新高度
	void ClearItem();						//需更新高度
	void SetItemContent(int Id,int Index,WCHAR* Text,DWORD Color);	//需更新高度
	void ShowItem(int Id,BOOL Visible);		//需更新高度
	void SetItemData(int Id,PVOID UserData);
	PVOID GetItemData(int Id);
	void SetSelectLimit(int MaxNum);
	BOOL IsItemSelected(int Id);
	void SelectItem(int Id,BOOL Select);	//选中规则为先入先出，后选中的会顶掉最先选中的
	int GetSelectedItem(int* IdArrayOut);	//缓冲区不能小于可选数量
	void CancelAllSelect();					//不对外提供修改滚动条位置的功能，而是取消全部选择时将滚动条重置

	//每个Item的高度不一定相同，无法通过乘法一次性计算，必须遍历累加
	//当Item显示或隐藏时，以及Item内的文本变更导致高度变化时，都会影响总高度
	//创建、删除、清空Item时，也会影响总高度
	//出于性能优化的考虑，没有每项修改完立即计算，而是要求全部修改完再一同计算
	//忘记调用此方法将会导致绘制和滚动条出现严重bug
	void ApplyItemChange();

private:
	int CalcItemHeight(CSpListBox::ItemDesc* Item);
	void DrawItem(int ItemX,int ItemY,CSpListBox::ItemDesc* Item);
	int ItemMouseHitTest(int ItemAreaPosX,int ItemAreaPosY);
	void SetSpViewPos(int NewPos);
	void SelectChangeCall();
};

//CEditable
//////////////////////////////////////////////////////////////////////////
class CEdit : public UIControl
{
public:
	//单行编辑框，固定22高度（字体14+上下边距各4）
	CEdit(WCHAR* Name,int X,int Y,int Width);
	virtual ~CEdit();

	virtual void Draw();
	virtual void Update();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);

	void AutoExtendBuffer(int MaxLen);
	void UpdateCharInfo(int StartPos);
	void InsertText(WCHAR* NewText,int InsertNum,int InsertPos);
	void DeleteText(int DeletePos,int DeleteNum);
	void SetText(WCHAR* NewText);
	void ClearText();
	int GetTextLen();
	void GetText(WCHAR* Buffer,int MaxChar);

	static const int MinAllocSize=3;
	static const int BodyPadding=4;
	static const int TextAreaX=4;
	static const int TextAreaY=4;
	FontR_t* FontText;
	int TextHeight;
	int TextAreaWidth;
	int TextAreaHeight;	//和字体高度有关

	//文本数据
	WCHAR* Text;
	int BufferLen;
	int TextLen;
	int* CharPosXInfo;
	int* CharWidthInfo;

	//状态管理
	BOOL FocusStatus;
	int CaretIndex;
	int CaretTimer;
	int TextViewPosX;
	BOOL SelectState;
	int SelBegIndex;;
	int SelectIndex;
	int SelectLen;

	int CharIndexToViewPos(int CharIndex);
	int ViewPosToCharIndex(int InputPos);
	int ViewPosToCaretIndex(int InputPos);
	void GetVisibleChar(int* FirstIndex,int* VisibleCount);
	void AlignView(int TargetPos);
	void MoveCaret(int NewCaretIndex);

	void TextCommandSelectAll();
	void TextCommandDelete();
	void TextCommandCopy();
	void TextCommandPaste();
	WCHAR* FilterText(WCHAR* RawText);

	//void ParseDigitalText();	//负号和百分号，小数点
};


//CAdjust
//////////////////////////////////////////////////////////////////////////
//由于微调按钮只会在特性系统用一次，而且完全可以被3个图片按钮替代，就不实现了
class CAdjust : public UIControl
{
public:
	CAdjust();
	virtual ~CAdjust();

	virtual void Draw()=0;
	virtual int Notify(UIEvent_t UIEvent,int Param1,int Param2)=0;
};


//OtherType
//////////////////////////////////////////////////////////////////////////
class CHSlider : public UIControl
{
public:
	CHSlider(WCHAR* Name,int X,int Y,int Width);	//固定高度15
	virtual ~CHSlider();

	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);

	float MinValue;
	float MaxValue;
	float Step;
	float Value;
	float ValueRatio;

	int BodyWidth;
	int BodyBegX;
	int BodyEndX;
	int SliderPosX;

	ImageR_t* ImgSlider;
    ImageR_t* ImgSliderDisable;

	void SetRange(float MinValue,float MaxValue,float Step);
	void SetValue(float NewValue);
	float GetValue();

	static const int SliderSize=15;
	static const int SliderCenter=8;
	static const int SlotHeight=3;

private:
	//基于BodyWidth，不是整个长度
	void SetSliderPos(int NewPos);
};

class CHTabView : public UIControl
{
public:
	BOOL PushedForClick;
	int PushX;
	int PushY;
	//int HoverIndex;	//持久的Push状态似乎和Hover是冲突的
	int DisplayIndex;		//只要不为空，一定有一个Tab在显示
	FontR_t* FontText;
	static const int TabHeight=30;
	int BodyHeight;

	ImageR_t* TabFullNormal;
	ImageR_t* TabLeftNormal;
	ImageR_t* TabRightNormal;
	ImageR_t* TabCenterNormal;
	ImageR_t* TabFullPush;
	ImageR_t* TabLeftPush;
	ImageR_t* TabRightPush;
	ImageR_t* TabCenterPush;

	struct TabItem 
	{
		UIControl* Page;
		WCHAR* Title;
	};

	std::vector<TabItem*> TabArray;

	CHTabView(WCHAR* Name,int X,int Y,int Width,int Height);	//顶部Tab高30
	virtual ~CHTabView();

	virtual void Draw();
	virtual int Notify(UIEvent_t UIEvent,PVOID Param1,PVOID Param2);
	//注意，内部调用UiMgr->InsertControl()将TabPage作为子页面插入，此后调用者失去TabPage所有权
	int InsertTabPage(UIControl* TabPage,WCHAR* Title,int InsertIndex);
	//注意，内部调用InsertControl()将TabPage作为子页面插入，此后调用者失去TabPage所有权
	int AppendTabPage(UIControl* TabPage,WCHAR* Title);
	//注意，内部调用UiMgr->DeleteControl()，整个控件及其子控件都会销毁，无法再回收利用
	void RemoveTabPage(int Index);
	//注意，内部调用UiMgr->DeleteControl()，整个控件及其子控件都会销毁，无法再回收利用
	void ClearItem();
	void SetDisplayTab(int Index);
    void SetTabTitle(int Index,WCHAR* Title);
};




